home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_13_02 / pipkin / startup.asm < prev    next >
Encoding:
Assembly Source File  |  1994-12-07  |  12.4 KB  |  305 lines

  1. [LISTING 4]
  2. ;=============================================================================
  3. ;
  4. ;  Start-up code for embedded C programs
  5. ;
  6. ;     intended for use with Microsoft C, but porting it to Borland C
  7. ;     or other similar compilers shouldn't be too difficult.
  8. ;
  9. ;  Donated to the public domain by Jeff D. Pipkins, who of course is
  10. ;  not liable for damages...
  11. ;
  12. ;
  13. ;  This file MUST be linked FIRST.  The linker will combine segments
  14. ;  with the same class name together, and it will order those combined
  15. ;  segments in the order that they first appear in this file.  This
  16. ;  is extremely important.  It is always the first file the linker
  17. ;  sees that gets to choose the ordering of the segments.
  18. ;
  19. ;-----------------------------------------------------------------------------
  20.  
  21. ROMSEG       EQU          0F800h       ; beginning of ROM
  22. STACKSIZE    EQU          4096
  23.  
  24. ;-----------------------------------------------------------------------------
  25. ;  data group (to fit in 64K)
  26. ;
  27. ;  For our model, we need the data to appear first in the image,
  28. ;  with the code up above it.  Unfortunately, we also need for
  29. ;  execution to begin at a fixed location known at build time,
  30. ;  and exe2bin wants that location to be either at offset 0 or
  31. ;  100h from the beginning of the image.  We solve this problem 
  32. ;  by putting a little code in the front of the data segment that 
  33. ;  can figure out where to jump.
  34. ;
  35. ;-----------------------------------------------------------------------------
  36.  
  37. DGROUP       group        NOTSTACK, NULL, CONST, _DATA, _BSS, STACK
  38.              assume       cs:DGROUP, ds:DGROUP
  39.              public       jumpstart
  40.  
  41.              ; The linker complains if there's no stack, and exe2bin
  42.              ; complains if there is.  This segment is here to fool
  43.              ; the linker.  See also the STACK segment, where exe2bin
  44.              ; is fooled.
  45.  
  46. NOTSTACK     segment      byte stack 'NOTSTACK'
  47.              ; This must remain empty.
  48. NOTSTACK     ends
  49.  
  50.  
  51. NULL         segment      para public 'NULL'
  52.  
  53.              ; The following bytes are the first bytes in the image.
  54.              ; MSC wants 16 bytes of 0's here.
  55.              ; We need to begin execution here as well...
  56.  
  57. jumpstart:
  58.              dw           8 dup (0)    ; 8  x  add  [bx+si], al
  59.  
  60.              ; There's already code in the reset vector to
  61.              ; do a cli & cld, but it's here again just for
  62.              ; emphasis, and more importantly, in case somebody
  63.              ; decides to modify the reset vector in the future.
  64.  
  65.              cli          ; interrupts off -- no stack yet, no vectors yet.
  66.              cld          ; initialize direction flag
  67.  
  68.              ; Compute segment address of "startup" label
  69.              ; The build process "locates" (provides fix-ups for) the 
  70.              ; image so that it will run properly if it is loaded into
  71.              ; a particular address in RAM.  This is what we want, since
  72.              ; our data will be copied into RAM.  Unfortunately, we
  73.              ; really need for our code segment to be "located" with
  74.              ; respect to the beginning of ROM instead.  We resolve
  75.              ; this dilemma in favor of the data, and then we'll set
  76.              ; the value of CS by hand.  This way, the code won't
  77.              ; know that it's in the wrong place.  This illusion will
  78.              ; all crash if anyone does a far jump, since the value
  79.              ; for CS will have been fixed-up incorrectly!  So, no
  80.              ; far jumps anywhere!  The only exception to this follows.
  81.              ; We get away with it because we compensate for the
  82.              ; miscalculation in advance.  (All of this hokey stuff is
  83.              ; a consequence of using exe2bin for a locator.)
  84.  
  85.              mov          dx, _TEXT    ; Segment address of code segment
  86.              mov          ax, ROMSEG   ; Should be same as CS for right now
  87.              add          dx, ax       ; Add fix-up for code segment
  88.              mov          ax, DGROUP   ; Segment address where data will be
  89.              sub          dx, ax       ; undo fix-up for data segment in RAM
  90.  
  91.              ; Temporarily use dword at DGROUP:0 to hold vector for jump.
  92.  
  93.              mov          ds, ax       ; DGROUP
  94.              xor          ax, ax
  95.              mov          word ptr ds:[0], ax
  96.              mov          word ptr ds:[2], dx  ; computed segment for jump
  97.  
  98.              jmp          dword ptr ds:[0]     ; to "startup"
  99.  
  100.              ; and now back to your regularly scheduled data...
  101.  
  102. NULL         ends
  103.  
  104.              ; Variables declared as "const" will go here.
  105.  
  106. CONST        segment      word public 'CONST'
  107. CONST        ends
  108.  
  109.              ; Initialized global and static variables will go here.
  110.  
  111. _DATA        segment      word public 'DATA'
  112.              public       __acrtused, _errno
  113. __acrtused   dw           0            ; prevents linking in Microsoft's
  114. _errno       dw           0            ; standard start-up code & libs
  115. _DATA        ends
  116.  
  117.              ; Uninitialized global and static variables will go here.
  118.              ; The C language guarantees that variables in this segment
  119.              ; will be initialized to 0 at load time.  It is up to the
  120.              ; startup code to make good on this promise.  Since we
  121.              ; are using exe2bin, it will fill in segments like this
  122.              ; one with zeros, but in many other environments, this
  123.              ; has to be done explicitly.  If you change the build
  124.              ; process so that this becomes necessary, perhaps the
  125.              ; easiest way to deal with it is to just begin by filling
  126.              ; all of RAM with zeros.  That way you'll also initialize
  127.              ; the FAR_BSS and HUGE_BSS at the same time, and you won't
  128.              ; have to figure out where any of them begin or end.
  129.  
  130. _BSS         segment      word public 'BSS'
  131. _BSS         ends
  132.  
  133.              ; Note: exe2bin doesn't want to see a stack segment because
  134.              ; it knows the loader won't be able to set up the stack as 
  135.              ; specified.  This startup code will set up this stack for us,
  136.              ; but we need to trick exe2bin so that it won't know this is
  137.              ; a stack.  So we define it as PUBLIC instead of STACK.
  138.  
  139. STACK        segment      word public 'STACK'
  140.              public       __stackend
  141.              db           STACKSIZE/8 dup ("<STACK> ")
  142. __stackend   label        word
  143. STACK        ends
  144.  
  145.  
  146. ;-----------------------------------------------------------------------------
  147. ;  data segments that are not part of dgroup
  148. ;-----------------------------------------------------------------------------
  149.  
  150. FAR_DATA_START segment    para public 'FAR_DATA'
  151. FAR_DATA_START ENDS
  152.  
  153. FAR_BSS_START segment     para public 'FAR_BSS'
  154. FAR_BSS_START ends
  155.  
  156. HUGE_BSS_START segment    para public 'HUGE_BSS'
  157. HUGE_BSS_START ends
  158.  
  159. ;-----------------------------------------------------------------------------
  160. ;  mark the end of all the data in the image
  161. ;-----------------------------------------------------------------------------
  162.  
  163. ENDDATAIMAGE    segment      para public 'ENDDATAIMAGE'
  164.                 public       __enddataimage
  165. __enddataimage  label        byte
  166. ENDDATAIMAGE    ends
  167.  
  168.  
  169. ;-----------------------------------------------------------------------------
  170. ;  Tell linker where to put the code segment.
  171. ;-----------------------------------------------------------------------------
  172.  
  173. _TEXT        segment      para public 'CODE'
  174. _TEXT        ends
  175.  
  176. ;-----------------------------------------------------------------------------
  177. ;  mark the end of the entire image
  178. ;-----------------------------------------------------------------------------
  179.  
  180. ENDIMAGE     segment      para public 'ENDIMAGE'
  181.              public       __endimage
  182. __endimage   label        byte
  183. ENDIMAGE     ends
  184.  
  185.  
  186. ;=============================================================================
  187. ;
  188. ;  Start-up code
  189. ;
  190. ;-----------------------------------------------------------------------------
  191.  
  192. _TEXT        segment
  193.              assume       CS:_TEXT, DS:DGROUP, SS:DGROUP
  194.  
  195.              extrn        _main:near
  196.              public       startup
  197. startup:
  198.              ;----------------------------------------------------------------
  199.              ; Initialize interrupt vectors to point to the restart vector.
  200.              ; This will cause a restart on any unexpected interrupt.
  201.              ;----------------------------------------------------------------
  202.  
  203.              xor          ax, ax
  204.              mov          ds, ax
  205.              xor          bx, bx
  206.              mov          cx, 256
  207. init_int_loop:
  208.              mov          [bx+0],  0FFF0h ; offset
  209.              mov          [bx+2], 0F000h  ; segment
  210.              add          bx, 4
  211.              loop         init_int_loop
  212.  
  213.              ;----------------------------------------------------------------
  214.              ; Set up a temporary stack 
  215.              ;----------------------------------------------------------------
  216.  
  217.              mov          ax, DGROUP
  218.              mov          ds, ax
  219.              mov          bx, offset DGROUP:__stackend
  220.              and          bx, NOT 1    ; align sp on word boundary
  221.              mov          ss, ax       ; DGROUP
  222.              mov          sp, bx       ; __stackend
  223.  
  224.              ;----------------------------------------------------------------
  225.              ; Copy data image from ROM to RAM
  226.              ;
  227.              ; For later processors with protected mode, this code assumes
  228.              ; that the ROM is reflected down into the top of the first
  229.              ; 1MB of address space.
  230.              ;----------------------------------------------------------------
  231.  
  232.              mov          ax, DGROUP
  233.              mov          es, ax
  234.              mov          dx, seg __enddataimage
  235.              sub          dx, ax       ; number of paragraphs to copy
  236.              mov          ax, ROMSEG
  237.              mov          ds, ax
  238. copyloop:
  239.              xor          si, si
  240.              xor          di, di
  241.              mov          cx, 8
  242.              rep          movsw
  243.  
  244.              mov          ax, es       ;\
  245.              inc          ax           ; > inc es
  246.              mov          es, ax       ;/
  247.  
  248.              mov          ax, ds       ;\
  249.              inc          ax           ; > inc ds
  250.              mov          ds, ax       ;/
  251.  
  252.              dec          dx
  253.              jnz          copyloop
  254.  
  255.              ;----------------------------------------------------------------
  256.              ; setup segment registers
  257.              ;----------------------------------------------------------------
  258.  
  259.              mov          ax, DGROUP
  260.              mov          ds, ax
  261.              mov          es, ax
  262.  
  263.              ;----------------------------------------------------------------
  264.              ; setup C stack and first frame
  265.              ;----------------------------------------------------------------
  266.  
  267.              mov          bx, offset DGROUP:__stackend
  268.              and          bx, NOT 1    ; align sp on word boundary
  269.              mov          ss, ax       ; DGROUP
  270.              mov          sp, bx       ; __stackend
  271.              xor          bp, bp       ; frame 0
  272.              push         bp           ;   mark it on the stack
  273.              mov          bp, sp       ; bp always has current frame pointer
  274.  
  275.              ;----------------------------------------------------------------
  276.              ; Call main()
  277.              ; note: CLI, CLD on entry.
  278.              ;----------------------------------------------------------------
  279.  
  280.              call         _main
  281.  
  282.              ;----------------------------------------------------------------
  283.              ; For embedded apps, main() should never return.
  284.              ; If for some reason it does, we'll start all over
  285.              ;----------------------------------------------------------------
  286.  
  287.              ; (for some reason, it's difficult to convince
  288.              ; the assembler to generate this instruction.)
  289.              db           0EAh         ; jmp far
  290.              dd           0F000FFF0h   ; restart vector
  291.  
  292.  
  293. _TEXT        ends
  294.  
  295. ;=============================================================================
  296. ;
  297. ;  Set entry point to beginning of image.
  298. ;  (This is done mostly to satisfy the assembler and exe2bin.)
  299. ;
  300. ;-----------------------------------------------------------------------------
  301.  
  302.              end          jumpstart
  303.  
  304.  
  305.